#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010, M = N * 2;

// h[]邻接表
// e[]链表存储的位置
// ne[]下一个指向
// idx当前位置
// st[]是否被搜过
int n;
int h[N], e[M], ne[M], idx;
bool st[N];

int ans = N; // 全局函数记录下点的最大值

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

// 以u为根的子树中点的数量
// 最终能够遍历所有的点，并递归找各个点的子树和，同时各个子树的连通块数与全局作比较
int dfs(int u)
{
    st[u] = true; // 标记一下，已经被搜过了，防止往上搜

    int sum = 1, res = 0;                  // 被搜索的该子树算1个点,res连通块最大值
    for (int i = h[u]; i != -1; i = ne[i]) // 遍历u所在的子树
    {
        int j = e[i]; // 该处所连子树的位置
        if (!st[j])   // 子树j没被搜过
        {
            int s = dfs(j);    // 获取该处子树的点的数量
            res = max(res, s); // 获取该点的最大子树
            sum += s;          // 累加得到当前点最大子树和加自己
        }
    }
    res = max(res, n - sum); // 当前根的最大子树
    ans = min(ans, res);     // 当前最大子树与全局的最小子树相比
    cout << "u:" << u << endl;
    cout << "res:" << res << endl;
    cout << "ans:" << ans << endl;
    cout << "sum:" << sum << endl;
    puts("");
    return sum;
}

int main()
{
    cin >> n; // n个结点
    memset(h, -1, sizeof h);

    // 把树看作无向图，每一个点都可以是树根
    for (int i = 0; i < n - 1; i++)
    {
        int a, b;
        cin >> a >> b;
        add(a, b), add(b, a); // 无向边
    }
    dfs(1);
    cout << ans << endl;
    return 0;
}